package edu.pku.sei.ocl.visitor.impl;


import edu.pku.sei.ocl.cst.OCLExpressionCS;
import edu.pku.sei.ocl.cst.OperationCallExpCS;
import edu.pku.sei.ocl.evaluation.Context;
import edu.pku.sei.ocl.evaluation.OCLVariable;
import edu.pku.sei.ocl.utilities.OCLConstant;
import edu.pku.sei.ocl.utilities.OCLStandardLibrary;
import edu.pku.sei.ocl.value.OCLCollection;
import edu.pku.sei.ocl.visitor.AbstractOCLVisitor;

public class ExpressionCheckVisitor extends AbstractOCLVisitor {
//	static {
//		expressionCheck = new ExpressionCheckVisitor();
//	}

	@Override
	public Object visitOperationCallExpCS(OperationCallExpCS expr,
			Context context) {
		String opName = expr.getSimpleNameCS().getValue();
		
		if("&&".equals(opName)){
			return checkAndExp(expr,context);
		} else if("||".equals(opName)){
			return checkOrExp(expr,context);
		} else if("=>".equals(opName)){
			return checkImpliesExp(expr,context);
		} else
			return super.visitOperationCallExpCS(expr, context);
	}

	private Object checkImpliesExp(OperationCallExpCS expr, Context context) {
		Object nv1 = expr.getSource().accept(this, context);
		if(OCLStandardLibrary.isFalse(nv1))
			return true;
		else if(OCLStandardLibrary.isTrue(nv1)){
			Object nv2 = expr.getArguments().get(0).accept(this, context);
			return nv2;
		} else
			return OCLConstant.OCLInvalid;
	}

	private Object checkAndExp(OperationCallExpCS expr, Context context) {
		
		Object nv1 = expr.getSource().accept(this, context);
		if(OCLStandardLibrary.isFalse(nv1))
			return false;
		else if(OCLStandardLibrary.isTrue(nv1)){
			Object nv2 = expr.getArguments().get(0).accept(this, context);
			return nv2;
		}
		else
			return OCLConstant.OCLInvalid;
	}
	
	private Object checkOrExp(OperationCallExpCS expr, Context context){
		Object nv1 = expr.getSource().accept(this, context);
		if(OCLStandardLibrary.isTrue(nv1))
			return true;
		else if(OCLStandardLibrary.isFalse(nv1)){
			Object nv2 = expr.getArguments().get(0).accept(this, context);
			return nv2;
		} else
			return OCLConstant.OCLInvalid;
	}
	
	protected Object doForEach(OCLVariable v1, OCLExpressionCS body,
			OCLCollection sourceCol, Context c) {
		return doForAll(v1,null,body,sourceCol,c);
	}

	protected Object doForEach(OCLVariable v1, OCLExpressionCS body,
			OCLCollection sourceCol, Context c,Object... expectedResult) {
		// TODO Auto-generated method stub
		return new Object[]{doForAll(v1,null,body,sourceCol,c),c};
	}
}
